package com.crjjason.utility.luckydraw;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

import org.apache.commons.math3.random.RandomDataGenerator;

/**
 * Represents a lucky draw
 * 
 * @author r.j.chen
 */
public class Draw {
	private List<Candidate> candidates;
	private List<Long> winners;
	private List<Long> backupWinners;
	private int winnerCount;
	private int backupCount;
	private boolean completed;
	
	public Draw(int winnerCount, int backupCount){
		if(winnerCount <= 0){
			throw new IllegalArgumentException("winner count should be greater than 0");
		}
		if(backupCount < 0){
			throw new IllegalArgumentException("backup count should be greater than or equal to 0");
		}
		candidates = new ArrayList<Candidate>();
		this.winnerCount = winnerCount;
		winners = new ArrayList<Long>();
		this.backupCount = backupCount;
		backupWinners = new ArrayList<Long>();
		completed = false;
	}
	
	
	public void addCandidate(String candidateName){
		Candidate candidate = new Candidate();
		candidate.setCandidateName(candidateName);
		candidate.setCandidateIdentifier(candidates.size() + 1);
		candidates.add(candidate);
	}
	
	public void draw(){
		if(completed){
			throw new IllegalStateException("the draw has been completed");
		}
		if((winnerCount + backupCount) > candidates.size()){
			throw new IllegalStateException("the draw cannot be completed");
		}
		RandomDataGenerator generator = new RandomDataGenerator();
		for(int counter = 0; counter < winnerCount; counter++){
			int winner = generator.nextInt(1, candidates.size());
			if(winners.contains(Long.valueOf(winner))){
				counter--;
				continue;
			}
			winners.add(Long.valueOf(winner));
		}
		for(int counter = 0; counter < backupCount; counter++){
			int winner = generator.nextInt(1, candidates.size());
			if(winners.contains(Long.valueOf(winner)) || backupWinners.contains(Long.valueOf(winner))){
				counter--;
				continue;
			}
			backupWinners.add(Long.valueOf(winner));
		}
		completed = true;
	}
	
	public List<Candidate> getWinners(){
		return getCandidatesFromIdentifiers(winners);
	}
	
	public List<Candidate> getBakcupWinners(){
		return getCandidatesFromIdentifiers(backupWinners);
	}
	
	private List<Candidate> getCandidatesFromIdentifiers(List<Long> identifiers){
		List<Candidate> result = new ArrayList<Candidate>();
		for(Long id : identifiers){
			for(Candidate candidate : candidates){
				if(candidate.getCandidateIdentifier() == id){
					result.add(candidate);
					break;
				}
			}
		}
		return result;
	}
}
